home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Documentation / Tech Notes & Articles / Recipes / Imaging & Layout / refcounting geometry recipe < prev    next >
Encoding:
Text File  |  1995-07-10  |  4.8 KB  |  92 lines  |  [TEXT/ttxt]

  1. OpenDoc™ Recipes
  2.  
  3.  
  4. Converting parts to use reference-counted geometry
  5. by the OpenDoc Design Team
  6. 26 Sep 94
  7.  
  8.  
  9. © 1993-1995  Apple Computer, Inc. All Rights Reserved.
  10. Apple, the Apple logo, and Macintosh are registered trademarks of Apple Computer, Inc.
  11. Mac and OpenDoc are trademarks of Apple Computer, Inc.
  12.  
  13.  
  14. OpenDoc b1c1 includes a change to the implementation of the Layout and Imaging subsystems that has a large effect on how part editor code must handle shape and transform objects. This document describes the change, and how to modify dependent code in part editors to work in a post-b1c1 world.
  15.  
  16. The change:
  17.  
  18. Classes ODShape and ODTransform are now derived from ODRefCntObject. This means shape and transform objects are now reference counted. Previously these objects were explicitly deleted, but now that they are reference counted, that is no longer possible.
  19.  
  20. There are a large number of calls in classes ODFacet and ODFrame that have shapes or transforms as either parameters or return values. The usage model for all of these calls has been changed. It’s easy to know which calls have changed – the calls in question all have a “biasCanvas” parameter – but basically any ODFacet or ODFrame call that involves a shape or transform has changed.
  21.  
  22. Modifying dependent code:
  23.  
  24. – Getters
  25.  
  26. • Most importantly, do not delete any geometry object returned from a frame or facet.
  27.  
  28. • Any call that returns geometry must be balanced by a subsequent Release() call on that object.  For example:
  29.  
  30. clipShape = facet->AcquireClipShape(ev, biasCanvas);
  31. ...
  32. clipShape->Release(ev);
  33. clipShape = kODNULL;
  34.  
  35. This applies to shapes and transforms which have just been created by factory methods as well. That is, newly created objects are born with a reference count of 1.
  36.  
  37. • Unfortunately, geometry can’t be used as conveniently in a functional fashion.  Wheras before you could say:
  38. myShape->Transform(ev, facet->GetContentTransform(ev));
  39. now you have to say:
  40.  
  41. contentTransform = facet->AcquireContentTransform(ev, biasCanvas);
  42. myShape->Transform(ev, contentTransform);
  43. contentTransform->Release(ev);
  44. contentTransform = kODNULL;
  45.  
  46. – Setters
  47.  
  48. • When you pass a shape or transform into a call, it is assumed the refcount of the object is at least one. You must give up ownership of the object to the frame or facet, so after you call the setter, you should release your reference to the object.
  49.  
  50. newShape = facet->CreateShape(ev);
  51. // fill in shape data...
  52. facet->ChangeClipShape(ev, newShape, biasCanvas);
  53. newShape->Release(ev);
  54. newShape = kODNULL;
  55.  
  56. The facet (or frame) will increment the geometry object’s refcount to keep it around. But make sure you don’t Release the object until after calling the setter, or the layout object won’t have a chance to increment its refcount before it drops to zero.
  57.  
  58. – Modifying geometry efficiently
  59.  
  60. • There are a number of calls on ODFrame and ODFacet that let you change the value of a shape or transform. Previously this necessitated a lot of copying. Now this can be accomplished more efficiently. Before you had to do
  61.  
  62. newShape = facet->AcquireClipShape(ev)->Copy(ev);
  63. // modify shape...
  64. facet->ChangeClipShape(ev, newShape);
  65.  
  66. Now you can do the following:
  67.  
  68. clipShape = facet->AcquireClipShape(ev, biasCanvas);
  69. // modify shape...
  70. facet->ChangeClipShape(ev, clipShape, biasCanvas);
  71. clipShape->Release(ev);
  72. clipShape = kODNULL;
  73.  
  74. This allows you to modify and re-use the same object without copying. It’s probably a good idea not to hang onto the modified shape, but rather get it again next time you want to use it. That way the memory can be reclaimed if the facet/frame goes away. More importantly, if the object changes for some reason, and you were modifying the object, not creating its value from scratch, you could end up with incorrect results. And it’s not that much overhead to get the object again later.
  75.  
  76. – Making copies
  77.  
  78. There is a utility function, ODCopyAndRelease, which can make copying of geometry both more convenient and more efficient. (You'll find it in the ODUtils utility.)  Here’s how you copy a shape:
  79.  
  80. frameShape = frame->AcquireFrameShape(ev, biasCanvas);
  81. clipShape = frameShape->Copy(ev);
  82. frameShape->Release(ev);
  83.  
  84. Using ODCopyAndRelease, here’s how you can do it:
  85.  
  86. clipShape = ODCopyAndRelease(ev, frame->AcquireFrameShape(ev, biasCanvas));
  87.  
  88. ODCopyAndRelease will copy the frameShape, and release it. For extra efficiency, if the refcount of the shape is exactly one, it will just return the shape itself (which is equivalent to copying and releasing it). There is an equivalent ODCopyAndRelease for Transforms as well.
  89.  
  90. – Automating release calls
  91.  
  92. A new C++ utility called TempObj can make it much simpler to keep track of objects that need to be released. It even ensures that the objects get released if an exception is thrown. For details, read the “Temporary Objects and References” document in the Tech Notes folder.